package cn.cscb.mms.server.service.impl;

import cn.cscb.mms.common.constant.Dict;
import cn.cscb.mms.common.context.BaseContext;
import cn.cscb.mms.common.exception.BaseException;
import cn.cscb.mms.pojo.entity.*;
import cn.cscb.mms.server.mapper.CustomerMapper;
import cn.cscb.mms.server.mapper.TaskInfoMapper;
import cn.cscb.mms.server.service.TaskInfoService;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.math.BigDecimal;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.sql.Date;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import java.util.Map;

@Service
public class TaskInfoServiceImpl implements TaskInfoService {

    @Resource
    private TaskInfoMapper taskInfoMapper;

    @Resource
    private CustomerMapper customerMapper;

    public IPage<TaskInfoVO> selectTaskList(TaskInfoParam taskInfoParam){

        LocalDate startTime = null;
        LocalDate endTime = null;
        if (StringUtils.isNotBlank(taskInfoParam.getPubStartTime())) {
            startTime = LocalDate.parse(taskInfoParam.getPubStartTime().substring(0,10), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }
        if (StringUtils.isNotBlank(taskInfoParam.getPubEndTime())) {
            endTime = LocalDate.parse(taskInfoParam.getPubEndTime().substring(0,10), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }

        Map params = new HashMap();
        if(StringUtils.isNotBlank(taskInfoParam.getMarkName())){
            params.put("markName", taskInfoParam.getMarkName());
        }
        if(StringUtils.isNotBlank(taskInfoParam.getMarkType())){
            params.put("markType", taskInfoParam.getMarkType());
        }
        if(StringUtils.isNotBlank(taskInfoParam.getMarkStatus())){
            params.put("markStatus", taskInfoParam.getMarkStatus());
        }
        Integer page = taskInfoParam.getPage();
        Integer pageSize = taskInfoParam.getPageSize();
        IPage p = new Page(page, pageSize);
        IPage<TaskInfoVO> pageResult = taskInfoMapper.selectTaskList(p, startTime, endTime, params);
        return pageResult;
    }


    public IPage<TaskInfo> selectList(Integer page, Integer pageSizer){
        QueryWrapper wrapper = new QueryWrapper();
        IPage p = new Page(page,pageSizer);
        return taskInfoMapper.selectPage(p, wrapper);
    }

    @Override
    public List<TaskInfo> selectAllTask() {
        return taskInfoMapper.selectAllTask();
    }

    @Override
    public IPage<HashMap<String,Object>> findAllMyMarket(String claimId, List<String> markStatus, List<String> markType, Date startDate, Date endDate, Integer page, Integer pageSizer) {

        HashMap<String,Object> paramMap = new HashMap<>();
        paramMap.put("claim_id",BaseContext.getCurrentEmpNo());
        paramMap.put("mark_status",markStatus);
        paramMap.put("mark_type",markType);
        paramMap.put("start_date",startDate);
        paramMap.put("end_date",endDate);
        IPage p = new Page(page, pageSizer);
        IPage<HashMap<String,Object>> pageResult = taskInfoMapper.findAllMyMarketByPage(p, paramMap);

        return pageResult;
    }

    @Override
    public TaskInfo getMarkInfo(Integer id) {
        QueryWrapper<TaskInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);
        wrapper.eq("state", Dict.RECORD_STATE_VALID.getCnName());
        return taskInfoMapper.selectOne(wrapper);
    }

    @Override
    public Integer updateMyMarket(Map<String,Object> map) {
        Integer id = (Integer) map.get("id");
        String isPhone = (String) map.get("is_phone");
        String isMeet =(String) map.get("is_meet");
        String markStatus = (String)map.get("mark_status");
        String feedbackStr = (String) map.get("feedback");
        QueryWrapper<TaskInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);
        wrapper.eq("state", Dict.RECORD_STATE_VALID.getCnName());
        TaskInfo taskInfo = taskInfoMapper.selectOne(wrapper);
        if(Dict.MARK_STATUS_SUCCESS.getCnName().equals(markStatus)){
            //营销成功
            taskInfo.setPoint(taskInfo.getReward());
            LocalDate date = LocalDate.now();
            taskInfo.setTaskEndDate(date);
        }else if(Dict.MARK_STATUS_FAILED.getCnName().equals(markStatus)){
            //营销失败
            taskInfo.setPoint(BigDecimal.ZERO);
            LocalDate date = LocalDate.now();
            taskInfo.setTaskEndDate(date);
        }
        if(Dict.YES.getCnName().equals(isPhone)){
            taskInfo.setIsPhone(isPhone);
        }
        if(Dict.YES.getCnName().equals(isMeet)){
            taskInfo.setIsMeet(isMeet);
        }
        BigDecimal feedback = BigDecimal.ZERO;
        if(StringUtils.isNotBlank(feedbackStr)){
            feedback = new BigDecimal(feedbackStr);
            taskInfo.setFeedback(feedback);
        }
        if(Dict.MARK_STATUS_FAILED.getCnName().equals(markStatus) || Dict.MARK_STATUS_SUCCESS.getCnName().equals(markStatus) || Dict.MARK_STATUS_MARKETTING.getCnName().equals(markStatus)){
            taskInfo.setMarkStatus(markStatus);
        }
        return taskInfoMapper.updateById(taskInfo);
    }

    @Override
    public Integer returnMyMarket(Map<String, Object> map) {
        Integer id = (Integer) map.get("id");
        QueryWrapper<TaskInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);
        wrapper.eq("state", Dict.RECORD_STATE_VALID.getCnName());
        TaskInfo taskInfo = taskInfoMapper.selectOne(wrapper);
        taskInfo.setClaimId(null);
        taskInfo.setTaskStartDate(null);
        taskInfo.setTaskEndDate(null);
        taskInfo.setIsPhone(null);
        taskInfo.setIsMeet(null);
        taskInfo.setFeedback(null);
        taskInfo.setPoint(null);
        return taskInfoMapper.updateById(taskInfo);
    }

    @Override
    public List<Map> getCus() {
        return taskInfoMapper.getCus();
    }

    @Override
    public Boolean isManager(String loginNo) {
        String duty  = taskInfoMapper.getEmpDuty(loginNo);
        if(duty.equals("02")){
            return true;
        }else{
            return false;
        }
    }


    @Override
    public TaskInfo addTaskList(TaskInfo taskInfo) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("mark_name", taskInfo.getMarkName());
        List list = taskInfoMapper.selectList(wrapper);
        if(list.size() > 0){
            throw new BaseException("该商机已经存在！新增商机失败！");
        }
        LocalDate date = LocalDate.now();
//        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//        String createTime = df.format(new Date());
//        Date date = null;
//        try {
//            date = df.parse(createTime);
//        }catch (ParseException e){
//            System.out.println(e.getMessage());
//        }
        taskInfo.setCreateDate(date);
        taskInfo.setMarkStatus("01");
        taskInfo.setState("01");
        taskInfoMapper.insert(taskInfo);
        return taskInfo;
    }

    @Override
    public Boolean deleteTask(String markNo) {
        TaskInfo taskInfo = taskInfoMapper.selectByMarktNo(markNo);
        if (taskInfo == null){
            throw new BaseException("不存在该条商机!");
        }
        if(taskInfo != null && taskInfo.getMarkStatus().equals("01")) {
            taskInfoMapper.deleteMark(taskInfo.getId());
            return true;
        }
        else{
            throw new BaseException("该商机已被认领，删除失败！");
        }
    }

    @Override
    public void deleteTaskList(List<String> markNoList) {
        for (String markNo : markNoList){
            TaskInfo taskInfo = taskInfoMapper.selectByMarktNo(markNo);
            if (taskInfo == null){
                throw new BaseException("不存在该条商机!");
            }
            if(taskInfo != null && taskInfo.getMarkStatus().equals("01")) {
                taskInfoMapper.deleteMark(taskInfo.getId());
            }
            else{
                throw new BaseException("该商机已被认领，删除失败！");
            }
        }
    }

    @Override
    public TaskInfo updateTask(TaskInfo taskInfo, Integer flag) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("mark_name", taskInfo.getMarkName());
        wrapper.notIn("mark_no", taskInfo.getMarkNo());
        List list = taskInfoMapper.selectList(wrapper);
        if(list.size() > 0){
            throw new BaseException("该商机已经存在！修改商机失败！");
        }
        if(flag == 0){
            TaskInfo taskInfoOrigin = taskInfoMapper.selectByMarktNo(taskInfo.getMarkNo());
            taskInfo.setCusId(taskInfoOrigin.getCusId());
        }
        taskInfoMapper.updateById(taskInfo);
        return taskInfo;
    }

    @Override
    public List<MarkStatus> getMarkStatus() {
        return taskInfoMapper.getMarkStatus();
    }

    @Override
    public List<MarkType> getMarkType() {
        return taskInfoMapper.getMarkType();
    }

    @Override
    public List<Map> getORG() {
        return taskInfoMapper.getORG();
    }

    @Override
    public List<Map> getAccountManager(String org) {
        return taskInfoMapper.getAccountManager(org);
    }

    @Override
    public Boolean distribution(String markNo, String disp, String claim) {
        TaskInfo taskInfo = taskInfoMapper.selectByMarktNo(markNo);
        if(taskInfo == null){
            throw new BaseException("所选择商机不存在！");
        }
        if (taskInfo.getMarkStatus().equals("02")) {
            throw new BaseException("所选择商机已被认领！");
        }
        if(taskInfo.getMarkStatus().equals("03") || taskInfo.getMarkStatus().equals("04")){
            throw new BaseException("所选择商机已被营销！");
        }
        return (taskInfoMapper.distribution(markNo, disp, claim));

    }

    @Override
    public Boolean claim(String markNo, String claim) {
        TaskInfo taskInfo = taskInfoMapper.selectByMarktNo(markNo);
        if(taskInfo == null){
            throw new BaseException("所选择商机不存在！");
        }
        if (taskInfo.getMarkStatus().equals("02")) {
            throw new BaseException("所选择商机已被认领！");
        }
        if(taskInfo.getMarkStatus().equals("03") || taskInfo.getMarkStatus().equals("04")){
            throw new BaseException("所选择商机已被营销！");
        }
        return (taskInfoMapper.claim(markNo, claim));

    }

    @Override
    public String getEmpNameByNo(String empNo) {
        return taskInfoMapper.getEmpNameByNo(empNo);
    }

    @Override
    public String getCUSNameByNo(String cusNo) {
        return taskInfoMapper.getCUSNameByNo(cusNo);
    }

    @Override
    public String getMarkTypeByNo(String typeNo) {
        return getMarkTypeByNo(typeNo);
    }

    @Override
    public String getMarkStatusByNo(String statusNo) {
        return getMarkStatusByNo(statusNo);
    }

    @Override
    public String getMarkTypeNoByTypeName(String typeName) {
        return taskInfoMapper.getMarkTypeNoByTypeName(typeName);
    }

    @Override
    public String getMarkStatusNoByStatusName(String statusNanme) {
        return taskInfoMapper.getMarkStatusNoByStatusName(statusNanme);
    }

    @Override
    public Boolean export(HttpServletResponse response)  throws Exception {
        // 从数据库查询出所有的数据
        List<TaskInfo> list = taskInfoMapper.selectAllTask();
        // 通过工具类创建writer 写出到磁盘路径
//        ExcelWriter writer = ExcelUtil.getWriter(filesUploadPath + "/用户信息.xlsx");
        // 在内存操作，写出到浏览器
        List<TaskInfoVO> taskInfoVOList = new ArrayList<>();
        String markType = "";
        String cusName = "";
        String createName = "";
        String markStatus = "";
        String dispName = "";
        String claimName = "";
        for(TaskInfo task : list){
            TaskInfoVO taskInfoVO = new TaskInfoVO();
            markType = taskInfoMapper.getMarkTypeByNo(task.getMarkType());
            cusName = taskInfoMapper.getCUSNameByNo(task.getCusId());
            createName = taskInfoMapper.getEmpNameByNo(task.getCreateId());
            markStatus = taskInfoMapper.getMarkStatusByNo(task.getMarkStatus());
            if(StringUtils.isBlank(task.getDispId())){
                dispName = "-";
            }else{
                dispName = taskInfoMapper.getEmpNameByNo(task.getDispId());
            }
            if(StringUtils.isBlank(task.getClaimId())){
                claimName = "-";
            }else{
                claimName = taskInfoMapper.getEmpNameByNo(task.getClaimId());
            }

            taskInfoVO.setMarkNo(task.getMarkNo());
            taskInfoVO.setMarkName(task.getMarkName());
            taskInfoVO.setMarkType(markType);
            taskInfoVO.setCusName(cusName);
            taskInfoVO.setCreateName(createName);
            taskInfoVO.setCreateDate(task.getCreateDate());
            taskInfoVO.setDescription(task.getDescription());
            taskInfoVO.setDispName(dispName);
            taskInfoVO.setClaimName(claimName);
            taskInfoVO.setReward(task.getReward());
            taskInfoVO.setMarkStatus(markStatus);
            taskInfoVOList.add(taskInfoVO);

        }
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //自定义标题别名
        writer.addHeaderAlias("markNo", "商机号");
        writer.addHeaderAlias("markName", "商机名");
        writer.addHeaderAlias("markType", "商机类型");
        writer.addHeaderAlias("cusName", "商机关联客户");
        writer.addHeaderAlias("description", "商机描述");
        writer.addHeaderAlias("createName", "商机创建人");
        writer.addHeaderAlias("createDate", "商机创建时间");
        writer.addHeaderAlias("reward", "商机激励值");
        writer.addHeaderAlias("markStatus", "商机状态");
        writer.addHeaderAlias("dispName", "商机派发人");
        writer.addHeaderAlias("claimName", "商机认领人");
        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(taskInfoVOList, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("markInfo", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();
        return true;
    }

    @Override
    public Boolean imp(MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        // 方式1：(推荐) 通过 javabean的方式读取Excel内的对象，但是要求表头必须是英文，跟javabean的属性要对应起来
//        List<User> list = reader.readAll(User.class);

        // 方式2：忽略表头的中文，直接读取表的内容
        List<List<Object>> list = reader.read(1);
//        List<TaskInfo> taskInfoList = CollUtil.newArrayList();
        List<String> haveSaveMark = new ArrayList<>();
        List<String> haveSaveCUS = new ArrayList<>();
        for (List<Object> row : list) {
            TaskInfo taskInfo = new TaskInfo();
            //判断关联客户是否存在
            String newMarkNo = row.get(0).toString();
            String newMarkName = row.get(1).toString();
            if(StringUtils.isBlank(newMarkNo) || StringUtils.isBlank(newMarkName)){
                returnMark(haveSaveMark);
                returnCUS(haveSaveCUS);
                throw new BaseException("导入失败，存在商机号或者商机名为空！");
            }
            String newCusId = row.get(3).toString();
            String newCusName = row.get(4).toString();
            if(StringUtils.isBlank(newCusId) || StringUtils.isBlank(newCusName)){
                returnMark(haveSaveMark);
                returnCUS(haveSaveCUS);
                throw new BaseException("导入失败，商机" + newMarkNo + "关联客户为空！");
            }
            Customer customer = customerMapper.getByIDandName(newCusId,newCusName);
            if(customer == null){
                Customer customerNew = new Customer();
                customerNew.setId(null);
                customerNew.setCusNo(newCusId);
                customerNew.setCusName(newCusName);
                customerNew.setState("1");
                customerMapper.insert(customerNew);
                haveSaveCUS.add(customerNew.getCusNo());
            }
            //判断派发人是否为管理者
            String newDispId = row.get(10).toString();
            String newDispName = row.get(11).toString();
            if(StringUtils.isNotBlank(newDispId) && StringUtils.isNotBlank(newDispName)){
                Employee employeeManager = taskInfoMapper.getEmpByIdAndName(newDispId, newDispName, "02");
                if(employeeManager == null){
                    returnMark(haveSaveMark);
                    returnCUS(haveSaveCUS);
                    throw new BaseException("派发人有误，不存在工号为"+ newDispId + "姓名为"+ newDispName + "的管理人员！");
                }
            }
            //认领人客户经理判断
            String newClaimId = row.get(12).toString();
            String newClaimName = row.get(13).toString();
            if(StringUtils.isNotBlank(newClaimId) && StringUtils.isNotBlank(newClaimName))
            {
                Employee employeeClaim = taskInfoMapper.getEmpByIdAndName(newClaimId, newClaimName, "01");
                if(employeeClaim == null){
                    returnMark(haveSaveMark);
                    returnCUS(haveSaveCUS);
                    throw new BaseException("认领人有误，不存在工号为"+ newClaimId + "姓名为"+ newClaimName + "的客户经理！");
                }
            }

            //判断状态与任务发放是否相符
            String status = row.get(9).toString();
            if(status.equals("未认领")){
                if(StringUtils.isNotBlank(newDispId) || StringUtils.isNotBlank(newDispName) || StringUtils.isNotBlank(newClaimId) || StringUtils.isNotBlank(newClaimName)){
                    returnMark(haveSaveMark);
                    returnCUS(haveSaveCUS);
                    throw new BaseException("商机" + newMarkNo +"的状态和派发情况不一致，导入失败！");
                }
            }
            taskInfo.setId(null);
            taskInfo.setMarkNo(row.get(0).toString());
            taskInfo.setMarkName(row.get(1).toString());
            taskInfo.setMarkType(taskInfoMapper.getMarkTypeNoByTypeName(row.get(2).toString()));
            taskInfo.setCusId(row.get(3).toString());
            taskInfo.setDescription(row.get(5).toString());
            taskInfo.setCreateId(row.get(6).toString());
            LocalDate createDate = LocalDate.now();
            taskInfo.setCreateDate(createDate);
            taskInfo.setReward(new BigDecimal(row.get(8).toString()));
            taskInfo.setMarkStatus(taskInfoMapper.getMarkStatusNoByStatusName(row.get(9).toString()));
            taskInfo.setDispId(row.get(10).toString());
            taskInfo.setClaimId(row.get(12).toString());
            taskInfo.setState("01");
            taskInfoMapper.insert(taskInfo);
            haveSaveMark.add(taskInfo.getMarkNo());
    }
        return true;
    }

    /**
     * 回退已导入商机
     * @param
     */
    public void returnMark(List<String> markNoList){
        for(String markNo: markNoList){
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("mark_no", markNo);
            taskInfoMapper.delete(wrapper);
        }

    }

    /**
     * 回退已导入关联客户
     * @param
     */
    public void returnCUS(List<String> cusNoList){
        for(String cusNo: cusNoList){
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("cus_no", cusNo);
            customerMapper.delete(wrapper);
        }

    }


    public Map getStatisticsBetweenDate(String startDate, String endDate) {
        Map result = new HashMap<>();
        Map ret = new HashMap<>();
        ret = taskInfoMapper.getMarkFinishedBetweenDate(startDate, endDate);
        result = taskInfoMapper.getDepositBetweenDate(startDate, endDate);

        ret.put("deposit", (result==null || result.isEmpty())?0:result.get("deposit"));
        result = taskInfoMapper.getLoanBetweenDate(startDate, endDate);
        ret.put("loan", (result==null || result.isEmpty())?0:result.get("loan"));
        return ret;
    }
}
